package net.wangds.yunz.auth.ctrl;

import io.swagger.annotations.ApiOperation;
import net.wangds.auth.module.User;
import net.wangds.auth.token.cache.TokenCache;
import net.wangds.yunz.auth.comp.AuthAccountComp;
import net.wangds.yunz.auth.service.AuthAccountService;
import net.wangds.yunz.auth.service.AuthService;
import net.wangds.yunz.auth.viewmodel.form.UploadFileForm;
import net.wangds.common.base.module.Holder;
import net.wangds.common.web.fileupload.module.FileBytes;
import net.wangds.common.web.fileupload.module.FileUploadData;
import net.wangds.common.web.fileupload.service.FileUploadServ;
import net.wangds.common.web.fileupload.viewmodel.form.FileUploadForm;
import net.wangds.jpa.Sorts;
import net.wangds.jpa.convertor.Page2MultipleRespConv;
import net.wangds.jpa.convertor.PagingForm2PageRequestConv;
import net.wangds.jpa.ctrl.AbstractJpaCompCtrl;
import net.wangds.log.helper.LogHelper;
import net.wangds.program.auth.module.AuthAccount;
//import net.wangds.program.comp.db.M16RefComp;
//import net.wangds.program.m20artarch.repository.mongo.ArchDocuRepo;
//import net.wangds.program.module.ArchOwnerStat;
//import net.wangds.program.module.M16Ref;
//import net.wangds.program.module.RefTypeEnum;
import net.wangds.utils.JsonUtils;
import net.wangds.web.entrypoint.BaseMultipleResp;
import net.wangds.web.entrypoint.BaseResp;
import net.wangds.web.entrypoint.PagingForm;
import net.wangds.web.utils.HttpDownloadHeaderUtils;
import net.wangds.web.viewmodel.IdForm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Iterator;

@RestController
@RequestMapping("/auth/account")
public class AccountCtrl  extends AbstractJpaCompCtrl<AuthAccount> {

    @Autowired
    private AuthAccountComp mmCmpAcc;

    @Autowired
    private TokenCache mmCchToken;

    private PagingForm2PageRequestConv mmCovPaging2Pr = new PagingForm2PageRequestConv(()->Sorts.createTm_desc);

    @Autowired
    private Page2MultipleRespConv<User> mmCovPg2Mr;

    @Autowired
    private FileUploadServ mmServUpld;

    @Autowired
    private AuthService mmServM10Auth;

    @Autowired
    private AuthAccountService mmServM11Acc;

    //@Autowired
    //private M16RefComp mmCmpRef;

    //@Autowired
    //private ArchDocuRepo mmMongoArch;

    @Override
    protected AuthAccountComp fetchJpaComp() {
        return mmCmpAcc;
    }


    @RequestMapping(value="/{id}/binded/users", method = RequestMethod.POST)
    public BaseMultipleResp<User> listBindedUsers(
            @PathVariable("id") String accId
    ){
        BaseMultipleResp<User> res = BaseMultipleResp.list(Collections.emptyList());
        mmCmpAcc.findById(accId).ifPresent(acc-> res.fill(mmCmpAcc.listAccountUsers(acc)));
        return res;
    }

    /**
     * 查询帐户的绑定用户备选列表.
     * @param accId 帐户id.
     * @param paging 分页信息.
     * @return 结果.
     */
    @RequestMapping(value="/{id}/unbinded/users", method = RequestMethod.POST)
    public BaseMultipleResp<User> listUnbindedUsers(
            @PathVariable("id") String accId
            , @RequestBody PagingForm paging
    ){
        Holder<Page<User>> h = Holder.of(null);
        mmCmpAcc.findById(accId).ifPresent(acc-> h.target = mmCmpAcc.listAccountUnbindUsers(acc, mmCovPaging2Pr.convert(paging)));
        return mmCovPg2Mr.convert(h.target);
    }


    @RequestMapping(value="/updateAccountNickname", method = RequestMethod.POST)
    public BaseResp<AuthAccount> updateAccountNickname(
            @RequestBody AuthAccount form
    ){
        LogHelper.dev(()->"更新昵称:"+ JsonUtils.toJsonStr(form.getIconId()));
        BaseResp<AuthAccount> res = BaseResp.<AuthAccount>of(null).code(-1);
        mmServM10Auth.updateCurrentAccount((acc)->{
            acc.setNickname(form.getNickname());
            res.code(0).body(acc);
        });
        return res;
    }


    @RequestMapping(value="/updateAccountIcon", method = RequestMethod.POST)
    public BaseResp<AuthAccount> updateAccountIcon(
           @RequestBody AuthAccount form
    ){

        LogHelper.dev(()->"更新头像:"+ JsonUtils.toJsonStr(form.getIconId()));
        BaseResp<AuthAccount> res = BaseResp.<AuthAccount>of(null).code(-1);
        mmServM10Auth.updateCurrentAccount((acc)->{
            acc.setIconId(form.getIconId());
            res.code(0).body(acc);
        });
        return res;
    }

    @RequestMapping(value="/uploadForm", method = RequestMethod.POST)
    public void uploadFile(MultipartHttpServletRequest req, HttpServletResponse resp){
        Iterator<String> filenames = req.getFileNames();
        if(filenames==null){
            return;
        }
        Holder<String> hld = Holder.of("");
        while(filenames.hasNext()){
            String filename = filenames.next();
            try {
                MultipartFile file = req.getFile(filename);
                if(file==null){
                    LogHelper.warn("上传文件内容为空:"+filename);
                    continue;
                }
                byte[] bytes = file.getBytes();
                String name = file.getName();
                String type = file.getContentType();
                long size = file.getSize();
                long tm = System.currentTimeMillis();
                LogHelper.dev("文件名:"+name+";内容："+bytes.length);
                mmServUpld.onUpload(FileUploadData.builder()
                        .content(bytes)
                        .type(type)
                        .size(size)
                        .filename(name)
                        .fileTm(tm)
                        .build()).ifPresent(entity->{
                            LogHelper.dev("文件记录:"+JsonUtils.toJsonStr(entity));
                            hld.target = entity.getId();
                });

            }catch (Exception ex){
                LogHelper.error(ex);
            }
        }

        try(OutputStream out = resp.getOutputStream()){
            //String url = req.getRequestURL().toString();
            String context = req.getHeader("X-ORIGIN-CONTEXT");
            //LogHelper.dev("url:"+req.getRequestURL().toString());

            out.write((context + "/auth/account/file/" + hld.target).getBytes(StandardCharsets.UTF_8));
            out.flush();
        } catch (IOException e) {
            LogHelper.error(e);
        }

    }

    @RequestMapping(value="/uploadFile", method = RequestMethod.POST)
    public BaseResp<String> uploadFile(
            @RequestBody UploadFileForm form
    ){

        LogHelper.dev(()->"/uploadFile:"+ JsonUtils.toJsonStr(form.getFilename()));

        BaseResp<String> res = BaseResp.<String>of(null).code(-1);

        mmServUpld.onUpload(FileUploadForm.builder()
                .content(form.getContent())
                .filename(form.getFilename())
                .fileTm(form.getTm())
                .type(form.getType())
                .size(form.getSize())
                .build()).ifPresent(f-> res.body(f.getId()).code(0));

        return res;
    }

    @RequestMapping(value="/download/{id}", method = RequestMethod.GET)
    public void downloadFile(
            @PathVariable("id") String fileId,
            HttpServletRequest req,
            HttpServletResponse resp
    ){
        FileBytes file = mmServUpld.loadFile(fileId);

        HttpDownloadHeaderUtils.writeAttachmentHeaders(file.getFilename(), req, resp);

        try(OutputStream os = resp.getOutputStream()){
            os.write(file.getContent());
            os.flush();
        } catch (IOException e) {
            LogHelper.error(e);
        }

    }


    @RequestMapping(value="/file/{id}", method = RequestMethod.GET)
    public void loadFile(
            @PathVariable("id") String fileId,
            HttpServletRequest req,
            HttpServletResponse resp
    ){
        FileBytes file = mmServUpld.loadFile(fileId);

        HttpDownloadHeaderUtils.writeFileHeaders(file.getFilename(), file.getType(), req, resp);

        try(OutputStream os = resp.getOutputStream()){
            os.write(file.getContent());
            os.flush();
        } catch (IOException e) {
            LogHelper.error(e);
        }

    }

    @Override
    public BaseMultipleResp<AuthAccount> listWithKeywords(PagingForm page) {

        return mmConvPage2Resp.convert(
                mmCmpAcc.findByKeywords(page.getKeywords(), mmConvPf2Pr.convert(page)));
    }

    //@RequestMapping(value="/stat/owner", method = RequestMethod.GET)
    //public BaseResp<ArchOwnerStat> statOwner(){
    //    return BaseResp.of(mmServM11Acc.stat(SpringAuthUtils.getCurrentUid()));
    //}

    /*
     * 是否关注指定的用户.
     * @param form 指定的用户.
     * @return 结果
     */
    /*
    @ApiOperation("登录用户是否关注表单用户")
    @RequestMapping(value="/isfollow2", method = RequestMethod.POST)
    public BaseResp<Boolean> isFollowTo(
            @RequestBody IdForm form
            ){
        String uid = SpringAuthUtils.getCurrentUid();
        return BaseResp.of(mmCmpRef.isRef(RefTypeEnum.ACCOUNT, uid, form.getId()));
    }
    */


    /*
     * 是否被指定的用户关注.
     * @param form 指定的用户.
     * @return 结果
     */
    /*
    @ApiOperation("表单用户是否关注登录用户")
    @RequestMapping(value="/isfollowedby", method = RequestMethod.POST)
    public BaseResp<Boolean> isFollowedBy(
            @RequestBody IdForm form
    ){
        String uid = SpringAuthUtils.getCurrentUid();
        return BaseResp.of(mmCmpRef.isRef(RefTypeEnum.ACCOUNT, form.getId(), uid));
    }

    @ApiOperation("关注关系")
    @RequestMapping(value="/followrefs", method = RequestMethod.POST)
    public BaseResp<Pair<Boolean, Boolean>> followRefs(
            @RequestBody IdForm form
    ){
        String uid = SpringAuthUtils.getCurrentUid();
        return BaseResp.of(Pair.of(
                mmCmpRef.isRef(RefTypeEnum.ACCOUNT, uid, form.getId()), //是否关注对方
                mmCmpRef.isRef(RefTypeEnum.ACCOUNT, form.getId(), uid) //对方是否关注你
        ));
    }

     */

    /*
     * 关注用户.
     * @param form 关注目标.
     * @return 结果.
     */
    /*
    @ApiOperation("关注用户")
    @RequestMapping(value="/follow", method = RequestMethod.POST)
    public BaseResp<Boolean> follow(
            @RequestBody IdForm form
    ){
        String uid = SpringAuthUtils.getCurrentUid();
        mmCmpRef.ref(RefTypeEnum.ACCOUNT, uid, form.getId());
        return BaseResp.of(true);
    }


    @RequestMapping(value="/unfollow", method = RequestMethod.POST)
    public BaseResp<Boolean> unfollow(
            @RequestBody IdForm form
    ){
        String uid = SpringAuthUtils.getCurrentUid();
        mmCmpRef.unref(RefTypeEnum.ACCOUNT, uid, form.getId());
        return BaseResp.of(true);
    }

     */

    /*
    @RequestMapping(value="/myfollows", method = RequestMethod.POST)
    @SuppressWarnings("unchecked")
    public BaseMultipleResp<M16Ref> myFollowToList(
            @RequestBody PagingForm form
    ){
        String uid = SpringAuthUtils.getCurrentUid();
        Page<M16Ref> list = mmCmpRef.listRef(RefTypeEnum.ACCOUNT, uid, new PagingForm2PageRequestConv(() -> Sorts.createTm_desc).convert(form));
        return new Page2MultipleRespConv().convert(list);

     */
        /*
        List<AuthAccount> usrlist = list.stream().map(ref -> mmServM10Auth.findByLoginname(ref.getTarget()).orElse(null))
                .map(u->
                    u.toMini()
                )
                .collect(Collectors.toList());

        return BaseMultipleResp.list(usrlist);
        */
    //}

/*
    @RequestMapping(value="/followme", method = RequestMethod.POST)
    @SuppressWarnings("unchecked")
    public BaseMultipleResp<M16Ref> followMe(
            @RequestBody PagingForm form
    ){
        String uid = SpringAuthUtils.getCurrentUid();
        Page<M16Ref> list = mmCmpRef.listRefByTarget(RefTypeEnum.ACCOUNT, uid, new PagingForm2PageRequestConv(() -> Sorts.createTm_desc).convert(form));

        return new Page2MultipleRespConv().convert(list);

 */
        /*
        List<AuthAccount> usrlist = list.stream().map(ref -> mmServM10Auth.findByLoginname(ref.getTarget()).orElse(null))
                .map(u->
                        u.toMini()
                )
                .collect(Collectors.toList());

        return BaseMultipleResp.list(usrlist);
        */
    //}

    /*
     * 关注藏品.
     * @param form 藏品.
     * @return 关注关系.
     */
    /*
    @RequestMapping(value="/followarchs", method = RequestMethod.POST)
    @SuppressWarnings("unchecked")
    public BaseMultipleResp<M16Ref> followArchs(
            @RequestBody PagingForm form
    ){
        String uid = SpringAuthUtils.getCurrentUid();
        Page<M16Ref> list = mmCmpRef.listRef(RefTypeEnum.ARCH, uid, new PagingForm2PageRequestConv(() -> Sorts.createTm_desc).convert(form));

        return new Page2MultipleRespConv().convert(list);
        */
        /*

        List<ArchDocu> usrlist = list.stream().map(ref -> mmMongoArch.findById(ref.getTargetId()).orElse(null))
                .collect(Collectors.toList());
        return BaseMultipleResp.list(usrlist);
        */
    //}

    /**
     * 获取指定的用户信息.
     * @param form 用户.
     * @return 用户信息.
     */
    @ApiOperation("获取指定的用户信息")
    @RequestMapping(value="/who", method = RequestMethod.POST)
    public BaseResp<AuthAccount> who(
            @RequestBody IdForm form
    ){
        return BaseResp.of(mmServM10Auth.findByLoginname(form.getId()).orElse(null));
    }

}
